// Copyright (c) Lawrence Livermore National Security, LLC and other VisIt
// Project developers.  See the top-level LICENSE file for dates and other
// details.  No copyright assignment is required to contribute to VisIt.

// ************************************************************************* //
//                            avtDenovoFileFormat.h                           //
// ************************************************************************* //

#ifndef AVT_Denovo_FILE_FORMAT_H
#define AVT_Denovo_FILE_FORMAT_H

#include <hdf5.h>
#include <avtSTMDFileFormat.h>
#include <InvalidFilesException.h>

#include <vector>

class avtMaterial;

// ****************************************************************************
//  Class: avtDenovoFileFormat
//
//  Purpose:
//      Reads in Denovo files as a plugin to VisIt.
//
//  Programmer: pugmire -- generated by xml2avt
//  Creation:   Fri Oct 6 11:06:44 PDT 2017
//
// ****************************************************************************

class avtDenovoFileFormat : public avtSTMDFileFormat
{
  public:
                       avtDenovoFileFormat(const char *);
    virtual           ~avtDenovoFileFormat() {}

    virtual void      *GetAuxiliaryData(const char *var,
                                        int domain,
                                        const char *type,
                                        void *args, 
                                        DestructorFunction &df);
    

    //
    // If you know the cycle number, overload this function.
    // Otherwise, VisIt will make up a reasonable one for you.
    //
    // virtual int         GetCycle(void);
    //

    virtual const char    *GetType(void)   { return "Denovo"; }
    virtual void           FreeUpResources(void); 

    virtual vtkDataSet    *GetMesh(int, const char *);
    virtual vtkDataArray  *GetVar(int, const char *);
    virtual vtkDataArray  *GetVectorVar(int, const char *);

  protected:
    virtual void           PopulateDatabaseMetaData(avtDatabaseMetaData *);
    void LoadFile();
    avtMaterial *GetMaterial(const std::string &var, int domain);

    bool fileLoaded;
    hid_t fileId;

    //Meta data.
    struct varInfo
    {
        varInfo() {}
        varInfo(hid_t fileId, const std::string &nm, const std::string &fileName) : name(nm)
        {
            if ((varId = H5Dopen(fileId, name.c_str(), H5P_DEFAULT)) < 0)
                EXCEPTION1(InvalidFilesException, fileName);
            if ((spaceId = H5Dget_space(varId)) < 0)
                EXCEPTION1(InvalidFilesException, fileName);
            
            dims.resize(H5Sget_simple_extent_ndims(spaceId));
            H5Sget_simple_extent_dims(spaceId, &dims[0], NULL);
            cout<<nm<<": dims= "<<dims.size()<<endl;
            /*
            if (dims.size() > 1)
                cout<<"CONSTRUCTION: "<<nm<<": "<<dims[0]<<" "<<dims[1]<<" "<<dims[2]<<" "<<dims[3]<<endl;
            */

            size_t pos = name.rfind("/");
            if (pos == std::string::npos)
                EXCEPTION1(InvalidFilesException, fileName);
        
            std::string vName = name.substr(pos+1);
            if (dims.size() < 4)
            {
                varNames.push_back(vName);
                cout<<"     SIMPLE "<<endl;
            }
            else
            {
                char tmp[64];
                for (int i = 0; i < dims[0]; i++)
                {
                    sprintf(tmp, "%s_%d", vName.c_str(), i);
                    varNames.push_back(tmp);
                }
            }
        }
        
        std::string name;
        std::vector<std::string> varNames;
        hid_t varId, spaceId;
        std::vector<hsize_t> dims;
    };
    std::vector<varInfo> coordMetaData;
    std::vector<varInfo> varMetaData;

    struct mixTableEntry
    {
        int row, col;
        double val;
    };
    std::vector<mixTableEntry> mixTable;
    std::vector<std::string> materialNames, materialColors;
};


#endif
